home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / apps / 255 / applic / cursive.c < prev    next >
C/C++ Source or Header  |  1988-06-14  |  9KB  |  316 lines

  1. /*      CURSIVE SIGNATURE PROGRAM       Version 0.10
  2.  *              (c) 1985 - Jan Wolter
  3.  *
  4.  *      Atari ST Port (c) 1988 - Darin Wayrynen
  5.  *
  6.  *
  7.  *  Purpose:    This program translates text into crude cursive script.
  8.  *      It works on any terminal with a fairly normal character
  9.  *      set (must have backslashes and underscores and suchlike).
  10.  *      The font includes all upper and lower case letters, most
  11.  *      punctuation, and a few symbols.  No numbers are included
  12.  *      (It's difficult to make a nice italicized set of numbers).
  13.  *      Cursive was originally written to generate fancy signatures
  14.  *      for electronic mail messages, but other uses may occur to
  15.  *      you.  The attractiveness of the font varies greatly with
  16.  *      the display device.
  17.  *
  18.  *  Usage:  If no command line arguments are given, cursive reads the
  19.  *      text to translate from standard input.  Otherwise the args
  20.  *      are translated (e.g. "cursive Jan Wolter" prints my name).
  21.  *      Output is always to standard output.  A couple command line
  22.  *      arguments are recognized:
  23.  *
  24.  *        -in   Sets the amount of space to insert between letters.
  25.  *          The default is "-i1".  "-i0" gives interesting
  26.  *          results.
  27.  *        -tn   Sets the length of the trailing line off the end
  28.  *          of each word.  The default is "-t1".
  29.  *
  30.  *      One character in the text is treated in a special way:
  31.  *
  32.  *        '_'   Can be inserted in text to slightly lengthen the
  33.  *          the spacing between two letters, or add a longer
  34.  *          tail to the end of a word.
  35.  *
  36.  *  Internals:  Unfortunately, the program is a kludge and the font is
  37.  *      somewhat difficult to edit.  It should be easy to port
  38.  *      though.  Systems with short integers or unsigned characters
  39.  *      should be no problem.  You should probably run "xstr" on the
  40.  *      font.c file, but if you haven't got "xstr", just compiling it
  41.  *      the usual way works fine.
  42.  *
  43.  *  Copyright:  Both the cursive program and the font it generates are
  44.  *      copyrighted by yours truly.  However, both may be used
  45.  *      and distributed freely.  You even have my permission to
  46.  *      sell it, or include in it a system that you sell.  I only
  47.  *      ask that my name be retained on this program, or any direct
  48.  *      decendents of this program with approximately the same
  49.  *      visibility as in this posting.
  50.  *
  51.  *  Mail:   I'm interested in any comments you have on this program.
  52.  *      I can be mailed at "janc@crim.eecs.umich.edu".  Better yet,
  53.  *      if you are into teleconferencing, call M-Net at (313) 994-6333
  54.  *      and type "newuser" at the "login:" prompt to give yourself an
  55.  *      account.  Send mail to janc, or join the "ugames" conference.
  56.  *
  57.  *      Have fun,
  58.  *                ___                _     __  _
  59.  *               (   >              ' )   /   // _/_
  60.  *                __/___.  ____      / / / __|/  /  _  __
  61.  *               / / (_/|_/ / <__   (_(_/ (_) \_<__</_/ (__
  62.  *              <_/
  63.  */
  64.  
  65. #include <stdio.h>
  66. #include "cursive.h"
  67.  
  68. char *buffer[6];    /* memory buffers to build up line in */
  69. int c[6];       /* current index in each of the buffer lines */
  70. int tail[6];        /* which buffer lines have tails in them */
  71. int lasttail;       /* which line was the last letter's tail */
  72. int space;      /* how much white space before the next letter */
  73. int interspace = 1; /* how much to spread adjacent letters out */
  74. int taillen = 1;    /* how long the tails on ends of words should be */
  75. char firstletter;   /* is this the first letter on the line? */
  76. char message[256] = ""; /* message to print */
  77.  
  78. char *malloc();
  79.  
  80. /* These are used by atoi */
  81.  
  82. #define TAB             '\t'
  83. #define PLUS            '+'
  84. #define MINUS           '-'     /* Redundant, but clearer */
  85. #define LEASTN          '0'
  86. #define MOSTN           '9'
  87.  
  88.  
  89. main(argc,argv)
  90. int argc;
  91. char **argv;
  92. {
  93. int i;
  94. char *s,*m;
  95. char ch;
  96.  
  97.     m = message;
  98.     for (i = 1; i < argc; i++)
  99.     {
  100.         if (*argv[i] == '-')
  101.             switch(ch = argv[i][1])
  102.             {
  103.             case 'i':
  104.             case 't':
  105.                 s = argv[i]+2;
  106.                 if (*s == '\000')
  107.                     if (++i < argc)
  108.                         s = argv[i];
  109.                 if (*s < '0' || *s > '9')
  110.                 {
  111.                     printf("%s: Illegal value %s\n",
  112.                         argv[0],s);
  113.                     exit(1);
  114.                 }
  115.                 if (ch == 'i')
  116.                     interspace = atoi(s);
  117.                 else
  118.                     taillen = atoi(s);
  119.                 break;
  120.             default:
  121.                 printf("usage: %s [-tn] [-in] message\n",
  122.                     argv[0]);
  123.                 exit(1);
  124.             }
  125.         else
  126.         {
  127.             if (m != message)
  128.                 *(m++) = ' ';
  129.             for (s=argv[i]; *s != '\000'; s++)
  130.                 *(m++) = *s;
  131.         }
  132.     }
  133.     /* Do the deed */
  134.     if (m != message)
  135.     {
  136.         /* Message from the arg list */
  137.         *(m++) = 0;
  138.         prline(message);
  139.     }
  140.     else
  141.     {
  142.         /* Message from standard input */
  143.         while (gets(message) != NULL)
  144.             prline(message);
  145.     }
  146. }
  147.  
  148.  
  149. /* Add the given letter to the end of the current line */
  150.  
  151. place(let)
  152. struct letter *let;
  153. {
  154. int i,j,n;
  155. int col;
  156. int maxx= -10000;
  157. char pad;
  158. char *l;
  159.  
  160.     if (firstletter)
  161.     {
  162.         col = space;        /* Leading spaces */
  163.         firstletter = 0;
  164.     }
  165.     else
  166.     {
  167.         /* Find the furthest left position we can place this letter */
  168.         for(i=0; i<6; i++)
  169.         {
  170.             if (let->line[i][0] != '\000' &&
  171.                 (col = c[i] - let->spcs[i]) > maxx)
  172.                 maxx = col;
  173.         }
  174.  
  175.         /* Insert some spaces between letters */
  176.         col = maxx + space + interspace;
  177.     }
  178.  
  179.     for(i=0; i<6; i++)
  180.  
  181.         /* If Nothing on this Line, Skip It */
  182.         if (let->line[i][0] != '\000')
  183.         {
  184.             /* Number of Spaces to Put on this Line? */
  185.             n = col - c[i] + let->spcs[i];
  186.  
  187.             /* Flyers off Ends of Letters */
  188.             if (tail[i])
  189.                 for (j = 0;
  190.                      j < 5 && n > space + 2; j++,n--)
  191.                     buffer[i][c[i]++] = '_';
  192.  
  193.             /* Connecting Lines Between Letters */
  194.             pad = (lasttail == i && let->tailin == i) ? '_' : ' ';
  195.  
  196.             /* In the middle of the intersection of South and */
  197.             /* East University, someone is playing the piano. */
  198.             for ( ; n > 0; n--)
  199.                 buffer[i][c[i]++] = pad;
  200.  
  201.             /* Copy in the letter text */
  202.             for (l = let->line[i]; *l != '\000'; l++)
  203.                 buffer[i][c[i]++] = *l;
  204.  
  205.             tail[i] = (i == let->tailout);
  206.         }
  207.  
  208.     lasttail = let->tailout;
  209.     space = 0;
  210. }
  211.  
  212. /* Lengthen the last trailer by n */
  213. tailer(n)
  214. int n;
  215. {
  216. int j;
  217.     if (lasttail >= 0)
  218.         for (j = 0; j < n; j++)
  219.             buffer[lasttail][c[lasttail]++] = '_';
  220. }
  221.  
  222. /* Handle a line */
  223. prline(s)
  224. char *s;
  225. {
  226. int l,i;
  227. char *ch;
  228. short lcode;
  229.  
  230.     lasttail = -1;
  231.     firstletter = 1;
  232.     space = 0;
  233.     /* Get some memory to put the output into */
  234.     l = strlen(s) * (CHARWIDTH + interspace);
  235.     for (i=0;i<6;i++)
  236.     {
  237.         buffer[i] = malloc((unsigned)l);
  238.         tail[i] = c[i] = 0;
  239.     }
  240.  
  241.     /* do each letter */
  242.     for (ch=s; *ch != '\000'; ch++)
  243.     {
  244.  
  245.         *ch &= '\177';
  246.         /* Find the letter */
  247.         lcode = (lasttail != 2) ? code1[*ch] : code2[*ch];
  248.         if (lcode >= 0)
  249.             place(&list[lcode]);
  250.         else
  251.             /* Various Special characters */
  252.             switch(lcode)
  253.             {
  254.             case SP:
  255.                 /* Insert white space before next letter */
  256.                 tailer(taillen);
  257.                 space += 3;
  258.                 lasttail = -1;
  259.                 break;
  260.             case ST:
  261.                 /* Lengthen the last tail */
  262.                 if (lasttail >= 0)
  263.                     buffer[lasttail][c[lasttail]++] = '_';
  264.                 break;
  265.             }
  266.     }
  267.     tailer(taillen);
  268.  
  269.     /* print the line and release the memory */
  270.     for (i=0;i<6;i++)
  271.     {
  272.         buffer[i][c[i]++] = '\n';
  273.         write(1,buffer[i],c[i]);
  274.         free(buffer[i]);
  275.     }
  276. }
  277.  
  278. /*
  279. **      atoi
  280. **
  281. **      Convert an ASCII string to an integer
  282. **
  283. */
  284.  
  285.  
  286. int atoi( ap )
  287. char *ap;
  288. {
  289.         register int n, c;
  290.         register char *p;
  291.         int f;
  292.  
  293.         p = ap;
  294.         n = 0;
  295.         f = 1;
  296.  
  297.         /* Scan the string for spaces or signs */
  298.         for( ; ;p++ ){
  299.                 if( *p == SP || *p == TAB || *p == PLUS )
  300.                         continue;
  301.                 if( *p == MINUS ){
  302.                         f = -f;
  303.                         continue;
  304.                 }
  305.                 break;
  306.         }
  307.  
  308.         /* Now assemble the number */
  309.         while( *p >= LEASTN && *p <= MOSTN )
  310.                 n = n*10 + *p++ - LEASTN;
  311.         if( f < 0 )
  312.                 n = -n;
  313.  
  314.         return( n );
  315. }
  316.